package com.gitee.magic.jdbc.persistence.source.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitee.magic.jdbc.persistence.RepositoryException;

/**
 * @author start
 */
public class SessionManager {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(SessionManager.class);
	
	private DataSource datasource;
	
	private ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {

		@Override
	    public Connection initialValue() {  
	        try {
				return getDatasource().getConnection();
			} catch (SQLException e) {
	     		throw new RepositoryException(e);
			}
	    }
	    
	};  

	public int executeUpdate(String sql,Object...params) throws SQLException{
		return executeUpdate1(false,sql,params);
	}
	
	/**
	 * @param generatedKeysFlag 是否返回生成的主键值
	 */
	public int executeUpdate1(boolean generatedKeysFlag, String sql,Object...params)throws SQLException{
		logConsole(sql);
		Connection conn=null;
		PreparedStatement pstmt=null;
		try{
			conn=getConnection();
			pstmt=generatedKeysFlag?
					conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS):
						conn.prepareStatement(sql);
			if(params!=null){
				for(int i=0;i<params.length;i++){
					pstmt.setObject(i+1, params[i]);
				}
			}
			int resultValue=pstmt.executeUpdate();
			if(generatedKeysFlag){
				ResultSet rSet=null;
				try{
					rSet=pstmt.getGeneratedKeys();
					while(rSet.next()){
						resultValue=rSet.getInt(1);
					}
				}finally{
					SessionManager.closeResultSet(rSet);
				}
			}
			return resultValue;
		}finally{
			SessionManager.closePreparedStatement(pstmt);
			SessionManager.closeConnection(conn);
		}
	}
	
	/**
	 * SQL批处理
	 */
	public int[] executeBatch(String... sqls) throws SQLException{
		Statement stmt=null;
		Connection conn=null;
		try{
			conn=getConnection();
			stmt=conn.createStatement();
			for(String batch:sqls){
				stmt.addBatch(batch);
				logConsole(batch);
			}
			return stmt.executeBatch();
		}finally{
			SessionManager.closeStatement(stmt);
			SessionManager.closeConnection(conn);
		}
	}
	
	public DataSource getDatasource() {
		return datasource;
	}

	public void setDatasource(DataSource datasource) {
		this.datasource = datasource;
	}
	
	/**
	 * 获取连接对象
	 */
	public Connection getConnection() throws SQLException {
		return connectionHolder.get();
	}
	
	/**
	 * 获取事务对象
	 */
	public TransactionManager getTransaction() throws SQLException{
		return new TransactionManager(getConnection());
	}

	////////////////////////////关闭对象/////////////////////
	
	public static void closeResultSet(ResultSet rset) {
		if (rset != null) {
			try {
				if(!rset.isClosed()){
					rset.close();
				}
			} catch (SQLException e) {
	     		throw new RepositoryException(e);
			}finally{
				rset = null;
			}
		}
	}
	
	public static void closeStatement(Statement stmt){
		if (stmt != null) {
			try {
				if(!stmt.isClosed()){
					stmt.close();
				}
			} catch (SQLException e) {
	     		throw new RepositoryException(e);
			}finally{
				stmt = null;
			}
		}
	}
	
	public static void closePreparedStatement(PreparedStatement pstmt) {
		if (pstmt != null) {
			try {
				if(!pstmt.isClosed()){
					pstmt.close();
				}
			} catch (SQLException e) {
	     		throw new RepositoryException(e);
			}finally{
				pstmt = null;
			}
		}
	}
	
	public static void closeConnection(Connection conn) {
		if (conn != null) {
			try {
				//不是自动提交则不关闭连接
				if(conn.getAutoCommit()){
					if(!conn.isClosed()){
						conn.close();
					}
				}
			} catch (SQLException e) {
	     		throw new RepositoryException(e);
			}finally{
				conn = null;
			}
		}
	}

	/**
	 * 打印SQL语句
	 */
	public static void logConsole(String sql){
		if(LOGGER.isDebugEnabled()) {
			LOGGER.debug(sql);
		}
	}
	
}